梦入琼楼寒有月,行过石树冻无烟

Spring security 会话管理

会话管理的基本概念可以理解为,管理会话的限制,就比如在大型的站点之中,基本上都是不允许多个帐号同时登录的,就比如腾讯QQ,假如PC1已经登入QQ,PC2再次登入QQ则会出现PC1QQ已经被踢下线的情况。而在网络设备中,只要该设备被登录,就不会允许再次登录的这种功能效果,Spring security为我们提供了完善的会话管理功能,和安全防御手段如:会话固定攻击,会话超时检测以及会话并发控制等。

什么是会话?

会话(session)即无状态的HTTP实现用户状态可维持的一种解决方案,在通常的情况每个请求之间都没有相互的关联性,也就是说用户访问的时候没有一个身份记录,也就是说谁都访问了,但是我不知道也查不到。session的出现解决了这个问题,服务器通过与用户达成一个约定,每个请求之间都携带着一个id类的信息

在用户首次访问的时候,系统会为该程序生成一个sessionId,并因此添加至cookie之中,当用户的会话期限内,每个请求都会自动携带该cookie,因此系统会轻易的判断这个识别是来此那个一个用户的请求。

Spring security 的会话固定攻击防御

在spring security之中,会话固定个攻击的防御手段也可通过用户登录之后重新生成新的session,在继承WebSecurityConfigurationAdapter的时候,Spring security则已经启用了这种配置。

sessionManagement

sessionManagement是一个会话管理的配置器,其中防御会话固定攻击的策略分为四种分别为:

WebSecurityConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.example.demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.anyRequest().authenticated()
.and().formLogin()
.and()
.rememberMe()
.userDetailsService(userDetailsService)
.and()
// 开启session会话管理
.sessionManagement()
.sessionFixation().none();
}

}

实际上在Spring security之中,即使没有配置,也不需要太过担心会话固定攻击,因为Security之中的HTTP防火墙或控制器会帮助我们拦截一定的不合法URL请求,就比如我压根没配置index,你访问了只能是Error Page的错误页。

Spring security 会话管理配置

在Spring security之中,我们可通过invalidSessionUrl来指定会话的失效时重定向的URL(默认重定向登录页面)。当然也可通过maximumSession来指定用户最大的并发数量(-1表示无限制),这里我们主要列举几个简单的例子来实现。

失效处理与失效时间

通过sessionManagement().invalidSessionUrl();来设置会话失效后重定向的页面,这里我们在application.propertoes中分别设置session与cokie的生命周期:

application.properties

1
2
3
4
5
6
7
8
spring.security.user.name=kun
spring.security.user.password=123

# 根据提示默认时间是30min(单位为秒),这里我们设置60m(一分钟),通过查看 TomcatServletWebServerFactory
# 我们可以得知session的默认时间是1分钟
server.servlet.session.timeout=60
# 这里是cookie的生命周期,单位为秒,-1是无限制
server.servlet.session.cookie.max-age=-1

WebSecurityConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.example.demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.anyRequest().authenticated()
.and().formLogin()
.and()
.rememberMe()
.userDetailsService(userDetailsService)
.and()
.sessionManagement()
.invalidSessionUrl("/myLogin.html");
}

}

由于我们并没有自定义登录页面所以```/myLogin.html `` `文件坐在resource/static目录下为空,所以在session会话失效的时候自然就跳转到了spring security为我们提供的默认登录页面之中,读者可根据需求自行进行修改与调整。

session 最大会话数量

通过.maximumSessions我们可以管理session中同一用户的最大会话数量,如果.maximumSessions设置为”-1“则表示无限制,除此之外的其他数字都将会被限制。而本次我们通过WebSecurityConfig.java中的.invalidSessionUrl来指定其同一用户登入后如session没过期的情况下跳转至/myLogin.html页面,而.maxSessionsPreventsLogin所表示的则是,用户session会话达到.maximumSessions的限制后,新的请求session将会被拒绝登录。

WebSecurityConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.example.demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.anyRequest().authenticated()
.and().formLogin()
.and()
.rememberMe()
.userDetailsService(userDetailsService)
.and()
.sessionManagement()
.invalidSessionUrl("/myLogin.html")
.maximumSessions(1).maxSessionsPreventsLogin(true);
}

}
⬅️ Go back